//
//  postgres.h
//  diylane-api
//
//  Created by Yucheng on 5/19/17.
//  Copyright © 2017 Yucheng. All rights reserved.
//

#ifndef postgres_h
#define postgres_h

#include <sqlpp11/sqlpp11.h>
#include <sqlpp11/postgresql/postgresql.h>
#include <vector>
#include <boost/thread.hpp>
#include "worker_pool.hpp"

namespace diylane
{
namespace postgres
{

struct Worker : pool::Worker
{
    sqlpp::postgresql::connection *conn_ = NULL;

    Worker(const std::shared_ptr<sqlpp::postgresql::connection_config> &config)
    {
        conn_ = new sqlpp::postgresql::connection(config);
    }

    ~Worker()
    {
        if (conn_)
        {
            delete conn_;
            conn_ = NULL;
        }
    }
};

struct Pool : pool::WorkerPool
{
    std::shared_ptr<sqlpp::postgresql::connection_config> config;

    Pool()
    {
        name = "postgres";
        config = std::make_shared<sqlpp::postgresql::connection_config>();
    }

    ~Pool()
    {
    }

    // singleton helper
    static Pool &singleton(void *uniquePtr = NULL)
    {
        static Pool *singletonPointer = NULL;
        if (uniquePtr)
            singletonPointer = (Pool *)uniquePtr;
        return *singletonPointer;
    }

    /// implementation of createOne_()
    ///
    /// @param error 接收错误信息
    /// @return <Worker*> 返回工作对象指针
    Worker *createOne_(std::string &error)
    {
        try
        {
            return new Worker(config);
        }
        catch (const std::exception &e)
        {
            error = e.what();
        }
        return NULL;
    }

    /// acquire a worker
    ///
    /// the returned worker must be released after use.
    /// @param error 接收错误信息
    /// @return <Worker*> 返回工作对象指针
    Worker *acquire(std::string &error)
    {
        return (Worker *)acquireWorker_(error);
    }
};

struct AcquiredWorker : pool::AcquiredWorker
{
    AcquiredWorker(Pool *_p, std::string &error)
    {
        pool = _p;
        w = _p->acquire(error);
    }
    ~AcquiredWorker() {}
    Worker *unwrap()
    {
        return (Worker *)w;
    }
};

struct PooledWorker
{
    Pool *pool = NULL;

    PooledWorker()
    {
    }

    virtual ~PooledWorker()
    {
    }

    /**
             * initialize connection pool
             */
    void initialize(Pool *p)
    {
        pool = p;
    }
};
}
}

#endif /* postgres_h */
